﻿using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Authorization.Users;
using Abp.Domain.Repositories;
using Abp.Linq.Extensions;
using Abp.Organizations;
using Abp.Runtime.Session;
using Microsoft.EntityFrameworkCore;
using Mt.Organizations;
using Mt.Site.Application.Dto;
using Mt.Site.Application.Organizations.Dto;
using Mt.Site.Application.Organizations.Posts.Dto;
using Mt.Site.Core.Authorization;
using Mt.Site.Core.Organizations;
using Mt.Site.Core.Organizations.Posts;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;

namespace Mt.Site.Application.Organizations.Posts
{
    [AbpAuthorize(AppPermissions.Pages_Administration_OrganizationUnits)]
    public class PostAppService : MtSiteAppServiceBase, IPostAppService
    {
        private readonly IRepository<MtOrganizationUnit, long> _organizationUnitRepository;
        private readonly IRepository<UserOrganizationUnit, long> _userOrganizationUnitRepository;
        private readonly IPostManager _postManager;

        public PostAppService(
            IRepository<MtOrganizationUnit, long> organizationUnitRepository,
            IRepository<UserOrganizationUnit, long> userOrganizationUnitRepository,
            IPostManager postManager)
        {
            _organizationUnitRepository = organizationUnitRepository;
            _userOrganizationUnitRepository = userOrganizationUnitRepository;
            _postManager = postManager;
        }

        [AbpAuthorize(PostPermissions.Pages_Administration_OrganizationUnits_Post_Create
            , PostPermissions.Pages_Administration_OrganizationUnits_Post_Edit)]
        public async Task CreateOrUpdatePostAsync(CreateOrUpdatePostInput input)
        {
            if (input.Post.Id > 0)
            {
                var post = await _postManager.Post.Where(c => c.Id == input.Post.Id).FirstOrDefaultAsync();
                if (post == null)
                {
                    return ;
                }
                ObjectMapper.Map(input.Post, post);
                await _postManager.CreateOrUpdateAsync(post, input.GrantedUnitIds, input.GrantedUserIds);
            }
            else
            {
                var post = ObjectMapper.Map<Post>(input.Post);
                post.TenantId = AbpSession.GetTenantId();
                await _postManager.CreateOrUpdateAsync(post, input.GrantedUnitIds, input.GrantedUserIds);
            }
        }

        [AbpAuthorize(PostPermissions.Pages_Administration_OrganizationUnits_Post_Delete)]
        public async Task DeletePostAsync(EntityIdListDto<long> input)
        {
            var items = await _postManager.Post.Where(c => input.List.Contains(c.Id)).ToListAsync();
            foreach (var item in items)
            {
                await _postManager.DeleteAsync(item);
            }
        }

        [AbpAuthorize(PostPermissions.Pages_Administration_OrganizationUnits_Post)]
        public async Task<PagedResultDto<PostEditDto>> GetOrganizationUnitPostsAsync(GetOrganizationUnitPostsInput input)
        {
            var query = from post in _postManager.Post
                        where post.OrganizationId == input.Id
                        select post;

            var totalCount = await query.CountAsync();
            var items = await query.OrderBy(input.Sorting).PageBy(input).ToListAsync();

            return new PagedResultDto<PostEditDto>(
                totalCount,
                items.Select(item => ObjectMapper.Map<PostEditDto>(item)).ToList()
                );
        }

        [AbpAuthorize(PostPermissions.Pages_Administration_OrganizationUnits_Post)]
        public async Task<GetPostForEditOutput> GetPostForEditAsync(GetPostForEditInput input)
        {
            var organizationUnits = await _organizationUnitRepository.GetAllListAsync(c => c.IsActive);
            var Users = await GetOrganizationUnitUsers2(input.OrganizationUnitId);
            var output = new GetPostForEditOutput
            {
                OrganizationUnits = ObjectMapper.Map<List<SimpleOrganinzationUnitDto>>(organizationUnits),
                Users = Users
            };
            output.OrganizationUnits = OrganizationUnitHelper.AdapterList(output.OrganizationUnits);
            foreach (var item in output.OrganizationUnits)
            {
                item.Order = Convert.ToInt32(OrganizationUnit.GetLastUnitCode(item.Code));
            }

            if (input.Id > 0)
            {
                var post = await _postManager.Post.Where(c => c.Id == input.Id).FirstOrDefaultAsync();
                if (post == null)
                {
                    return null;
                }

                output.Post = ObjectMapper.Map<PostEditDto>(post);
                output.GrantedUnitIds = await _postManager.GetPostOrganizationListAsync(post.Id);
                output.GrantedUserIds = await _postManager.GetPostUserListAsync(post.Id);

                return output;
            }
            else
            {
                output.Post = new PostEditDto { OrganizationId = input.OrganizationUnitId, PostLevel = PostGroup.Member };
                output.GrantedUnitIds = new List<long>();
                output.GrantedUserIds = new List<long>();

                return output;
            }
        }
        private async Task<List<OrganizationUnitUserListDto>> GetOrganizationUnitUsers2(long unitId)
        {
            var query = from ouUser in _userOrganizationUnitRepository.GetAll()
                        join ou in _organizationUnitRepository.GetAll() on ouUser.OrganizationUnitId equals ou.Id
                        join user in UserManager.Users on ouUser.UserId equals user.Id
                        where ouUser.OrganizationUnitId == unitId
                        select user;

            var items = await query.OrderByDescending(c=>c.Order).Distinct().ToListAsync();

            return ObjectMapper.Map<List<OrganizationUnitUserListDto>>(items);
        }

        [AbpAuthorize(PostPermissions.Pages_Administration_OrganizationUnits_Post_Edit)]
        public async Task SwapPostSortNumber(SwapSortNumberInput<long> input)
        {
            var idList = input.IdOrderList.Select(c => c.Id).ToList();
            var orderList = input.IdOrderList.Select(c => c.Order).ToList();

            if (idList.Count == 0)
            {
                return;
            }

            var list = await _postManager.Post.Where(c => idList.Contains(c.Id)).ToListAsync();
            foreach (var item in list)
            {
                var index = idList.FindIndex(c => c == item.Id);
                if (index != -1)
                {
                    item.Order = orderList[index];
                }
            }
        }

        [AbpAuthorize(PostPermissions.Pages_Administration_OrganizationUnits_Post_Edit)]
        public async Task SetPostNewSorNumber(NewSortNumberInput<long> input)
        {
            var post = await _postManager.Post.Where(c => c.Id == input.Id).FirstOrDefaultAsync();
            post.Order = input.NewNumber;
        }

        [AbpAuthorize(PostPermissions.Pages_Administration_OrganizationUnits_Post_Edit)]
        public async Task SetPostStatus(SetStatusInput<long> input)
        {
            var post = await _postManager.Post.Where(c => input.IdList.Contains(c.Id)).ToListAsync();
            foreach (var item in post)
            {
                item.IsActive = input.IsActive;
            }
        }
    }
}